package com.ruoyi.common.utils.math;


import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import ch.obermuhlner.math.big.*;

public class MathUtils {

    /**
     * @param q
     * @param k
     * @param ap
     * @param efficiency
     * @return 催化剂总体积 m³
     */
    public static BigDecimal zv(BigDecimal q, BigDecimal k, BigDecimal ap, BigDecimal efficiency) {
        //q取反
        BigDecimal q1 = q.negate();
        //1 - efficiency
        BigDecimal oneMinusEfficiency = new BigDecimal("1").subtract(efficiency);
        //oneMinusEfficiency的自然对数
        BigDecimal oneMinusEfficiencyLog = new BigDecimal(Math.log(oneMinusEfficiency.doubleValue()));
        //k * ap
        BigDecimal kAp = k.multiply(ap);
        return q1.multiply(oneMinusEfficiencyLog).divide(kAp, 2, RoundingMode.HALF_UP);
    }


    /**
     * 催化剂实际用量Vc
     * @param h
     * @param n
     * @return
     */
    public static BigDecimal vc(BigDecimal h,BigDecimal n){
        return n.multiply(h).multiply(new BigDecimal("0.466").multiply(new BigDecimal("0.466")));
    }

    /**
     * 实际余量
     * @param vc
     * @param zv
     * @return
     */
    public static BigDecimal rc(BigDecimal vc, BigDecimal zv){
        return vc.divide(zv, 2, RoundingMode.HALF_UP);
    }

    /**
     * 实际余量在1-1.3之间
     * @param rc
     * @return
     */
    public static boolean checkRc(BigDecimal rc){
        if(rc.compareTo(new BigDecimal("1.3")) > 0){
            return false;
        } else if (rc.compareTo(new BigDecimal("1.0"))< 0) {
            return false;
        } else {
            return true;
        }
    }
    /**
     * @param q   烟气标况下流量
     * @param k   末期活性系数
     * @param k0  活性数据
     * @param ap  催化剂几何表面积【查询出，根据型号绑定】
     * @param efficiency
     * @return 催化剂总体积 m³
     */
    public static BigDecimal zv2(BigDecimal q, BigDecimal k,BigDecimal k0, BigDecimal ap, BigDecimal efficiency) {
        //q取反
        BigDecimal q1 = q.negate();
        //1 - efficiency
        BigDecimal oneMinusEfficiency = new BigDecimal("1").subtract(efficiency);
        //oneMinusEfficiency的自然对数
        BigDecimal oneMinusEfficiencyLog = new BigDecimal(Math.log(oneMinusEfficiency.doubleValue()));
        //k * ap
        BigDecimal kAp = k.multiply(k0).multiply(ap);
        return q1.multiply(oneMinusEfficiencyLog).divide(kAp, 2, RoundingMode.HALF_UP);
    }

    /**
     * 反应器截面积
     *
     * @param q
     * @return
     */
    public static BigDecimal s(BigDecimal q) {
        return s(q, new BigDecimal("1.5"));
    }

    /**
     * 反应器截面积
     *
     * @param q
     * @return
     */
    public static BigDecimal s(BigDecimal q, BigDecimal flowRate) {
        return q.divide(flowRate, 2, RoundingMode.HALF_UP).divide(new BigDecimal("3600"), 2, RoundingMode.HALF_UP);
    }

    /**
     * 催化剂高度
     *
     * @return
     */
    public static BigDecimal totalH(BigDecimal zv, BigDecimal s) {
        return zv.divide(s, 2, RoundingMode.HALF_UP);
    }

    /**
     * 矩阵比较
     *
     * @param x
     * @param y
     * @param s
     * @return
     */
    public static boolean check(Integer x, Integer y, BigDecimal s) {
        BigDecimal max = s.multiply(new BigDecimal("1.1"));
        BigDecimal middle = new BigDecimal(x).multiply(new BigDecimal("0.466")).multiply(new BigDecimal(y)).multiply(new BigDecimal("0.466"));
        if (middle.compareTo(max) > 0) {
            return false;
        } else if (s.compareTo(middle) > 0) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * 单层催化剂高度
     *
     * @param h
     * @param cs
     * @return
     */
    public static BigDecimal singleH(BigDecimal h, BigDecimal cs) {
        return h.divide(cs, 2, RoundingMode.HALF_UP).multiply(new BigDecimal("100"));
    }

    /**
     * @param c1
     * @param c2
     * @return
     */
    public static BigDecimal efficiency(BigDecimal c1, BigDecimal c2) {
        return c1.subtract(c2.multiply(new BigDecimal("1.0")))
//                .multiply(new BigDecimal("100"))
                .divide(c1, 2, RoundingMode.HALF_UP);
    }

    /**
     * 开平方
     */
    public static BigDecimal sqrt(BigDecimal x) {
        return BigDecimalMath.sqrt(x, MathContext.DECIMAL64);
    }

    /**
     * 选择催化剂类型
     * @param h
     * @return
     */
    public static String switchCatalystsType(BigDecimal h) {
        if (h.compareTo(new BigDecimal("250")) <= 0) {
            return "H";
        } else if (h.compareTo(new BigDecimal("250")) > 0 && h.compareTo(new BigDecimal("270")) <= 0) {
            return "K";
        } else if (h.compareTo(new BigDecimal("270")) > 0 && h.compareTo(new BigDecimal("500")) <= 0) {
            return "A";
        } else if (h.compareTo(new BigDecimal("500")) > 0 && h.compareTo(new BigDecimal("520")) <= 0) {
            return "HK";
        } else if (h.compareTo(new BigDecimal("520")) > 0 && h.compareTo(new BigDecimal("540")) <= 0) {
            return "E";
        } else if (h.compareTo(new BigDecimal("540")) > 0 && h.compareTo(new BigDecimal("620")) <= 0) {
            return "AHs-120";
        } else if (h.compareTo(new BigDecimal("620")) > 0 && h.compareTo(new BigDecimal("670")) <= 0) {
            return "EHs-130";
        } else if (h.compareTo(new BigDecimal("670")) > 0 && h.compareTo(new BigDecimal("750")) <= 0) {
            return "AH";
        } else if (h.compareTo(new BigDecimal("750")) > 0 && h.compareTo(new BigDecimal("770")) <= 0) {
            return "AK";
        } else if (h.compareTo(new BigDecimal("770")) > 0 && h.compareTo(new BigDecimal("790")) <= 0) {
            return "EH";
        } else if (h.compareTo(new BigDecimal("790")) > 0 && h.compareTo(new BigDecimal("810")) <=0) {
            return "EK";
        } else if (h.compareTo(new BigDecimal("810")) > 0 && h.compareTo(new BigDecimal("900")) <= 0) {
            return "AAS-400";
        }  else if (h.compareTo(new BigDecimal("900")) > 0 && h.compareTo(new BigDecimal("940")) <= 0) {
            return "EAs-400";
        }else if (h.compareTo(new BigDecimal("940")) > 0 && h.compareTo(new BigDecimal("1000")) <= 0) {
            return "AA";
        } else if (h.compareTo(new BigDecimal("1000")) > 0 && h.compareTo(new BigDecimal("1040")) <= 0) {
            return "AE";
        } else if (h.compareTo(new BigDecimal("1040")) > 0 && h.compareTo(new BigDecimal("1080")) <= 0) {
            return "EE";
        } else if (h.compareTo(new BigDecimal("1080")) > 0 && h.compareTo(new BigDecimal("1120")) <= 0) {
            return "AAHs-120";
        } else if (h.compareTo(new BigDecimal("1120")) > 0 && h.compareTo(new BigDecimal("1210")) <= 0) {
            return "EEHs-130";
        } else if (h.compareTo(new BigDecimal("1210")) > 0 && h.compareTo(new BigDecimal("1250")) <= 0) {
            return "AHA";
        } else if (h.compareTo(new BigDecimal("1250")) > 0 && h.compareTo(new BigDecimal("1500")) <= 0) {
            return "AAA";
        }
        return "";
    }

    /**
     *
     * @param q 烟气入口浓度
     * @param o2 氧气占比
     * @param inNox 入口Nox浓度
     * @param h20  水含量
     * @param outNox 出口Nox浓度
     * @return
     */

    public static BigDecimal nh3Consume(BigDecimal q,BigDecimal o2, BigDecimal inNox, BigDecimal h20, BigDecimal outNox){
        //(21-o2)/21
        BigDecimal fo2 = new BigDecimal("21").subtract(o2).divide(new BigDecimal("18"), 2, RoundingMode.HALF_UP);
        //1- h20/100
        BigDecimal fh2o = new BigDecimal("1").subtract( (h20.divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP)));

        BigDecimal million = new BigDecimal("1000000");
        //q*(21-o2)/18*inNox/1000000/46*22.4*(1-h20/100)
        BigDecimal fNoxIn = q.multiply(fo2).multiply(inNox).divide(new BigDecimal("46"), 2, RoundingMode.HALF_UP).multiply(new BigDecimal("22.4")).multiply(fh2o).divide(million, 2, RoundingMode.HALF_UP);
        //outNox *(21-o2)/18*q/1000000/46*22.4*(1-h20/100)
        BigDecimal fNoxOut = outNox.multiply(fo2).multiply(q).divide(new BigDecimal("46"), 2, RoundingMode.HALF_UP).multiply(new BigDecimal("22.4")).multiply(fh2o).divide(million, 2, RoundingMode.HALF_UP);

        //2.5*q/1000000*(21-o2)/18*(1-h20/100)/17*22.4
        BigDecimal fNh3Slip = new BigDecimal("2.5").multiply(q).multiply(fo2).multiply(fh2o).divide(new BigDecimal("17"), 2, RoundingMode.HALF_UP).multiply(new BigDecimal("22.4")).divide(million, 2, RoundingMode.HALF_UP);

        //(fNoxIn- fNoxOut + fNh3Slip)/22.4*17
        return fNoxIn.subtract(fNoxOut).add(fNh3Slip).divide(new BigDecimal("22.4"), 2, RoundingMode.HALF_UP).multiply(new BigDecimal("17"));

    }


    /**
     * 催化剂单层阻力降
     * @param t    烟气温度
     * @param aperture 催化剂孔径【用波纹高度】
     * @param h         催化剂高度
     * @param q         入口烟气流量
     * @param matrixX   矩阵X
     * @param matrixY    矩阵Y
     * @param frictionalDrag  阻力系数
     * @param fmCoefficient  fm系数
     * @return
     */
    public static BigDecimal pressure(BigDecimal t, BigDecimal aperture, BigDecimal h,  BigDecimal q, Integer matrixX, Integer matrixY, BigDecimal frictionalDrag, BigDecimal fmCoefficient) {
        BigDecimal s = new BigDecimal(matrixX).multiply(new BigDecimal("0.466")).multiply(new BigDecimal(matrixY)).multiply(new BigDecimal("0.466"));
        //催化剂孔内流速（工况、湿基、实际氧）
        BigDecimal u = q.divide(new BigDecimal("3600").multiply(s),2,RoundingMode.HALF_UP);

        //粘度
        BigDecimal viscosity = new BigDecimal("-0.00002").multiply(t).multiply(t).add(new BigDecimal("0.0476").multiply(t)).add(new BigDecimal("15.799"));
        //密度
        BigDecimal density = new BigDecimal("-0.000000008").multiply(t).multiply(t).multiply(t)
                .add(new BigDecimal("0.000009").multiply(t).multiply(t))
                .add(new BigDecimal("-0.0042").multiply(t))
                .add(new BigDecimal("1.3"))
                ;
        //雷诺数 Re=d*u*ρ/μ
        BigDecimal re = aperture.multiply(new BigDecimal("0.001")).multiply(u).multiply(density).divide(viscosity.multiply(new BigDecimal("0.000001")), 3, RoundingMode.HALF_UP);

        //14.227/re
        BigDecimal fm = fmCoefficient.divide(re, 5, RoundingMode.HALF_UP);

        //催化剂单层阻力降 △Pa=2*Fm*ρ*u^2/d*L+λ*ρ*u^2/2
        return new BigDecimal("2").multiply(fm).multiply(density).multiply(u).multiply(u).multiply(h).multiply(new BigDecimal("1000")).divide(aperture, 0, RoundingMode.HALF_UP)
                .add(frictionalDrag.multiply(density).multiply(u).multiply(u).divide(new BigDecimal("2"), 0, RoundingMode.HALF_UP));
    }

    public static void main(String[] args) {
        System.out.println(pressure(new BigDecimal("280"), new BigDecimal("5.1"), new BigDecimal("0.790"), new BigDecimal("136939"), 20, 4, new BigDecimal("1.5"), new BigDecimal("14.227")));
    }
}